package com.summer.framework.redis.service;

import com.fasterxml.jackson.core.type.TypeReference;

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * Description: redis服务类
 * @auther Ice Yang
 * Date 2025/7/2
 */
public interface RedisService {


    /**
     * 设置键的过期时间
     * @param key 键
     * @param timeout 时间
     * @param unit 时间单位
     */
    void expire(String key, long timeout, TimeUnit unit);

    /**
     * 设置键的过期时间（Duration方式）
     * @param key 键
     * @param duration 持续时间
     */
    void expire(String key, Duration duration);

    /**
     * 删除键
     * @param key 键
     * @return 是否删除成功
     */
    Boolean delete(String key);

    /**
     * 批量删除键
     * @param keys 键集合
     * @return 删除的数量
     */
    Long delete(Collection<String> keys);

    /**
     * 检查键是否存在
     * @param key 键
     * @return 是否存在
     */
    Boolean hasKey(String key);

    /**
     * 获取剩余过期时间
     * @param key 键
     * @return 剩余时间（秒）
     */
    Long getExpire(String key);

    /********************** 单个对象操作 **********************/

    /**
     * 存储单个对象
     * @param key 键
     * @param value 值
     */
    void setObject(String key, Object value);

    /**
     * 存储单个对象并设置过期时间
     * @param key 键
     * @param value 值
     * @param timeout 过期时间
     * @param unit 时间单位
     */
    void setObject(String key, Object value, long timeout, TimeUnit unit);

    /**
     * 获取单个对象
     * @param key 键
     * @return 对象
     */
    Object getObject(String key);

    /**
     * 获取指定类型的对象
     * @param key 键
     * @param clazz 对象类型
     * @return 对象
     */
    <T> T getObject(String key, Class<T> clazz);

    /**
     * 获取复杂泛型对象
     * @param key 键
     * @param typeReference 类型引用
     * @return 对象
     */
    <T> T getObject(String key, TypeReference<T> typeReference);

    /**
     * 更新对象
     * @param key 键
     * @param updateFunction 更新函数
     * @return 更新后的对象
     */
    <T> T updateObject(String key, Class<T> clazz, Function<T, T> updateFunction);

    /********************** List操作 **********************/

    /**
     * 存储List
     * @param key 键
     * @param list 列表
     */
    <T> void setList(String key, List<T> list);

    /**
     * 存储List并设置过期时间
     * @param key 键
     * @param list 列表
     * @param timeout 过期时间
     * @param unit 时间单位
     */
    <T> void setList(String key, List<T> list, long timeout, TimeUnit unit);

    /**
     * 获取整个List
     * @param key 键
     * @param elementType 元素类型
     * @return 列表
     */
    <T> List<T> getList(String key, Class<T> elementType);

    /**
     * 获取List分页
     * @param key 键
     * @param elementType 元素类型
     * @param start 开始索引
     * @param end 结束索引
     * @return 分页列表
     */
    <T> List<T> getListRange(String key, Class<T> elementType, long start, long end);

    /**
     * 向List添加元素
     * @param key 键
     * @param element 元素
     * @return 操作后List长度
     */
    <T> Long addToList(String key, T element);

    /**
     * 向List添加多个元素
     * @param key 键
     * @param elements 元素集合
     * @return 操作后List长度
     */
    <T> Long addToList(String key, Collection<T> elements);

    /**
     * 更新List中的元素
     * @param key 键
     * @param index 索引
     * @param newValue 新值
     */
    void updateListElement(String key, long index, Object newValue);

    /**
     * 删除List中指定值的元素
     * @param key 键
     * @param value 要删除的值
     * @param count 删除数量（>0从头开始，<0从尾开始，0全部）
     * @return 删除的数量
     */
    Long removeFromList(String key, Object value, long count);

    /********************** Set操作 **********************/

    /**
     * 存储Set
     * @param key 键
     * @param set 集合
     */
    <T> void setSet(String key, Set<T> set);

    /**
     * 存储Set并设置过期时间
     * @param key 键
     * @param set 集合
     * @param timeout 过期时间
     * @param unit 时间单位
     */
    <T> void setSet(String key, Set<T> set, long timeout, TimeUnit unit);

    /**
     * 获取整个Set
     * @param key 键
     * @param elementType 元素类型
     * @return 集合
     */
    <T> Set<T> getSet(String key, Class<T> elementType);

    /**
     * 向Set添加元素
     * @param key 键
     * @param elements 元素
     * @return 添加成功的数量
     */
    <T> Long addToSet(String key, T... elements);

    /**
     * 从Set移除元素
     * @param key 键
     * @param elements 元素
     * @return 移除的数量
     */
    Long removeFromSet(String key, Object... elements);

    /**
     * 检查元素是否在Set中
     * @param key 键
     * @param element 元素
     * @return 是否存在
     */
    Boolean isSetMember(String key, Object element);

    /********************** Hash操作 **********************/

    /**
     * 存储整个 Map
     * @param key 键
     * @param map 哈希表
     */
    <T> void setHashAll(String key, Map<String, T> map);

    /**
     * 获取整个Hash
     * @param key 键
     * @param valueType 值类型
     * @return 哈希表
     */
    <T> Map<String, T> getHashAll(String key, Class<T> valueType);

    /**
     * 设置Hash字段值
     * @param key 键
     * @param field 字段
     * @param value 值
     */
    void setHashValue(String key, String field, Object value);

    /**
     * 获取Hash字段值
     * @param key 键
     * @param field 字段
     * @param valueType 值类型
     * @return 值
     */
    <T> T getHashValue(String key, String field, Class<T> valueType);

    /**
     * 删除Hash字段
     * @param key 键
     * @param fields 字段
     * @return 删除的数量
     */
    Long deleteHashFields(String key, String... fields);

    /**
     * 检查Hash字段是否存在
     * @param key 键
     * @param field 字段
     * @return 是否存在
     */
    Boolean hasHashKey(String key, String field);

    /**
     * 原子递增
     * @param key 键
     * @param delta 增量
     * @return 递增后的值
     */
    Long increment(String key, long delta);

    /**
     * 原子递减
     * @param key 键
     * @param delta 减量
     * @return 递减后的值
     */
    Long decrement(String key, long delta);

    /**
     * 发布消息
     * @param channel 频道
     * @param message 消息
     */
    void publish(String channel, Object message);

    String generate(String prefix) throws Exception;

    String generateWithTime(String prefix) throws Exception;

    String generate(String prefix, int length) throws Exception;

    String generateWithTime(String prefix, int length) throws Exception;
}
